var model = require('../public/scripts/game.js'),
	nodeunit = require('nodeunit');

exports['engine'] = nodeunit.testCase({

	setUp : function(callback) {
		this.player = stubPlayer();
		callback();
	},

	'win if all tiles cleared' : function (test) {
		var game = createGame(withBoard([[false]]), this.player);

		game.touch(coord(0,0));

		test.equal(this.player.hasWon, true);	
		test.deepEqual(this.player.lastReceivedState, [[tileIs('CLEARED', 0)]] );
		test.done();
	},

	'lose if player touches mine and display other mines' : function (test) {
		var game = createGame(withBoard([[true, true]]), this.player);
	
		game.touch(coord(0,0));
		
		test.equal(this.player.hasLost, true);	
		test.deepEqual(this.player.lastReceivedState, [[tileIs('MINE','?'), tileIs('MINE', '?')]]);
		test.done();
	},

	'uncleared tiles are covered' : function (test) {
		var game = createGame(withBoard(
					[[false, true],
					 [false, true]]), this.player);

		game.touch(coord(0,0));
		test.deepEqual(this.player.lastReceivedState,
				[[tileIs('CLEARED', 2),   tileIs('COVERED', '?')],
				 [tileIs('COVERED', '?'), tileIs('COVERED', '?')]]);
		test.done();
	},

	'adjacent tiles that are not adjacent to mines are uncovered' : function (test) {
		
		var game = createGame(withBoard(
					[[false, false],
					 [false, false]]), this.player);

		game.touch(coord(0,0));
		test.deepEqual(this.player.lastReceivedState,
				[[tileIs('CLEARED', 0), tileIs('CLEARED', 0)],
				 [tileIs('CLEARED', 0), tileIs('CLEARED', 0)]]);
		test.done();
	},

	'slamming clears all adjacent tiles' : function (test) {

		var game = createGame(withBoard(
					[[false, false, true],
					 [false, false, true],
					 [false, false, true]]), this.player);

		game.touch(coord(0,1));
		game.slam(coord(0,1));
		test.deepEqual(this.player.lastReceivedState,
				[[tileIs('CLEARED', 0), tileIs('CLEARED', 2), tileIs('COVERED', '?')],
				 [tileIs('CLEARED', 0), tileIs('CLEARED', 3), tileIs('COVERED', '?')],
				 [tileIs('CLEARED', 0), tileIs('CLEARED', 2), tileIs('COVERED', '?')]]);
		test.done();
	}
	
});

function createGame(mineFieldDesigner, player){
	return new model.Game(player,mineFieldDesigner.width, mineFieldDesigner.height, mineFieldDesigner);
}

function tileIs(state, numberOfAdjacentMines){
	return { state: state, numberOfAdjacentMines: numberOfAdjacentMines};
}

function stubPlayer(){
	return {
		hasWon : false,
		hasLost : false,
		win : function (){
			this.hasWon = true;
		},
		lose : function (state){
			this.hasLost = true;
			this.lastReceivedState = state.grid;
		},
		update : function (state){
			this.lastReceivedState = state.grid;
		},
		error : function (){},


	};
}

function withBoard(board) {
	return 	{
		create : function () {return board;},
		width : board[0].length,
		height : board.length
	};
}

function coord(xCoord,yCoord) {
	return {x:xCoord, y:yCoord};
}


